#include "ParticleEngine.h"
#include "CEmitter.h"
#include "SGD Wrappers/CSGD_TextureManager.h"

ParticleEngine::~ParticleEngine()
{
	for(unsigned int i = 0; i < m_vEmittersPool.size(); ++i)
		delete m_vEmittersPool[i];

	for(unsigned int i = 0; i < m_vActiveEmitters.size(); ++i)
		delete m_vActiveEmitters[i];
}
int ParticleEngine::Load(string filename)
{
	int a = filename.size() - 3;
	if(filename[filename.size() - 3] == 'b')
	{
		fstream in(filename.c_str(), ios_base::binary|ios_base::in);

		if(in.is_open())
		{
			CEmitter* temp_emitter = new CEmitter();
			int temp_int = 1;

			in.read((char*)&temp_int, 4);
			temp_emitter->SetParticleStartAlpha(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleStartRed(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleStartGreen(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleStartBlue(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleEndAlpha(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleEndRed(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleEndGreen(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleEndBlue(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleStartScale((float)temp_int/100.0f);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleEndScale((float)temp_int/100.0f);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleMinLife(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleMaxLife(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleVelMinX(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleVelMaxX(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleVelMinY(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleVelMaxY(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleAccelMinX(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleAccelMaxX(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleAccelMinY(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticleAccelMaxY(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetParticlesPerSec(temp_int);

			char temp_string[255];
			in.read((char*)&temp_int, sizeof(int));
			in.seekg(1, ios_base::cur);
			in.read(temp_string, sizeof(char)*temp_int);

			if(temp_string == "0")
				temp_emitter->SetParticleID(-1);
			else
			{
				string buffer = "resources\\particle effects\\";
				for(unsigned int i = 1; i < temp_int; ++i)
				{
					buffer += temp_string[i];
				}
				temp_emitter->SetParticleID(CSGD_TextureManager::GetInstance()->LoadTexture(buffer.c_str()));
			}

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetEmitterSize(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetEmitterType(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetSourceBlendID(temp_int);

			in.read((char*)&temp_int, sizeof(int));
			temp_emitter->SetDestinationBlendID(temp_int);

			m_vEmittersPool.push_back(temp_emitter);

			in.close();

			return 1;
		}
	}

	return -1;
}
int* ParticleEngine::AddEffect(int EmitterID, int EmitterLife, float fPosX, float fPosY, bool bLooping)
{
	int* temp_int = NULL;
	if(EmitterID < m_vEmittersPool.size())
	{
		CEmitter* temp_emitter = new CEmitter(*m_vEmittersPool[EmitterID]);
		temp_emitter->SetPosX(fPosX);
		temp_emitter->SetPosY(fPosY);
		temp_emitter->SetEmitterLife(EmitterLife);
		temp_emitter->SetIsActive(true);
		temp_int = new int;
		*temp_int = m_vActiveEmitters.size();
		temp_emitter->SetLooping(bLooping);
		temp_emitter->SetEmitterID(temp_int);
		m_vActiveEmitters.push_back(temp_emitter);
	}
	return temp_int;
}
void ParticleEngine::RemoveEffect(int* EmitterID)
{
	m_vEmittersToRemove.push_back(EmitterID);
}

void ParticleEngine::RemoveAllEffects()
{
	int temp_size = m_vActiveEmitters.size();

	for(unsigned int i = 0; i < temp_size; ++i)
	{
		delete m_vActiveEmitters[i];
	}
	m_vActiveEmitters.clear();
}

void ParticleEngine::Update(float fElapsedTime)
{
	vector<CEmitter*> temp_Emitters;
	for(unsigned int i = 0; i < m_vActiveEmitters.size(); ++i)
	{
		bool need_continue = false;
		if(m_vEmittersToRemove.size())
		{
			vector<int*> temp_vInts;
			for(unsigned int j = 0; j < m_vEmittersToRemove.size(); ++j)
			{
				if(*m_vEmittersToRemove[j] != i)
					temp_vInts.push_back(m_vEmittersToRemove[j]);
				else
				{
					delete m_vActiveEmitters[i];
					m_vEmittersToRemove.clear();
					m_vEmittersToRemove = temp_vInts;
					need_continue = true;
					break;
				}
			}
			m_vEmittersToRemove.clear();
			m_vEmittersToRemove = temp_vInts;
		}

		if(need_continue)
			continue;

		m_vActiveEmitters[i]->Update(fElapsedTime);

		if(m_vActiveEmitters[i]->GetIsActive() == true)
			temp_Emitters.push_back(m_vActiveEmitters[i]);
		else
			delete m_vActiveEmitters[i];
	}

	m_vActiveEmitters.clear();

	m_vActiveEmitters = temp_Emitters;

	for(unsigned int i = 0; i < m_vActiveEmitters.size(); ++i)
	{
		m_vActiveEmitters[i]->SetEmitterID(i);
	}
}
void ParticleEngine::Render()
{
	for(unsigned int i = 0; i < m_vActiveEmitters.size(); ++i)
		m_vActiveEmitters[i]->Render();
}
void ParticleEngine::SetEmitterInfo(int EmitterID, float fPosX, float fPosY, float EmitterSize)
{
	if(m_vActiveEmitters.size() > EmitterID)
	{
		m_vActiveEmitters[EmitterID]->SetPosX(fPosX);
		m_vActiveEmitters[EmitterID]->SetPosY(fPosY);

		if(EmitterSize > 0)
			m_vActiveEmitters[EmitterID]->SetEmitterSize(EmitterSize);
	}
}